import os
import time
from datetime import datetime
import pytest
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains, Keys

@pytest.fixture( scope="function" )
def driver():
    # 提交最终代码脚本时，请将驱动路径换回官方路径"C:\\Users\\86153\\AppData\\Local\\Google\\Chrome\\Application\\chromedriver.exe"
    service = Service(
        executable_path="D:\\Software\\Chrome\\Driver\\chromedriver.exe")
        # executable_path="C:\\Users\\86153\\AppData\\Local\\Google\\Chrome\\Application\\chromedriver.exe" )
    driver = webdriver.Chrome( service=service )
    driver.get( "https://map.baidu.com/" )
    driver.maximize_window()
    driver.implicitly_wait( 10 )
    yield driver
    driver.quit()


class TestBaiDuMap:

    # test-code-start

    # 定位元素
    __WAY = (By.XPATH,"/html/body/div[1]/div[2]/div/div[1]/div/div[2]")
    __LEAVE_INPUT = (By.XPATH,"/html/body/div[1]/div[2]/div/div[1]/div[2]/div[2]/div/div[2]/div[1]/input")
    __ARRIVE_INPUT = (By.XPATH,"/html/body/div[1]/div[2]/div/div[1]/div[2]/div[2]/div/div[2]/div[2]/input")
    __QUERY_BUTTON = (By.XPATH,"/html/body/div[1]/div[2]/div/button")
    __MOD = [
        # 推荐路线组件
        (By.ID, "type0"),
        # 时间花费最少组件
        (By.ID, "type5"),
        # 换乘少组件
        (By.ID, "type2"),
        # 步行少组件
        (By.ID, "type3")
    ]
    __CITY_SELECTOR = (By.XPATH,"/html/body/div[1]/div[3]/div[3]/div/div[1]/a")
    __CITY_SELECTOR_NANJING = (By.XPATH,"/html/body/div[3]/div[1]/div[2]/div/div[1]/div[4]/form/input")
    __ROAD_STATUS = (By.XPATH,"/html/body/div[1]/div[3]/div[3]/div/div[2]/div[1]")
    __REALTIME_ROAD_STATUS = (By.XPATH,"//a[@citycode='315' and @name ='南京']")
    __REFRESH_BUTTON = (By.XPATH,"/html/body/div[1]/div[3]/div[3]/div/div[3]/div[1]/div/div/div[2]/span[3]")
    __CITY_SELECTOR_SUBMIT = (By.XPATH,"/html/body/div[3]/div[1]/div[2]/div/div[1]/div[4]/form/span")
    __PREDICT_ROAD_STATUS = (By.XPATH,"/html/body/div[1]/div[3]/div[3]/div/div[3]/div[1]/div/div/div[1]/div[1]/span[2]")
    __WEEK_DAY = (By.XPATH,"/html/body/div[1]/div[3]/div[3]/div/div[3]/div[1]/div/div/div[2]/table/tbody/tr[1]/td")
    __TIME_POINT = (By.XPATH,"/html/body/div[1]/div[3]/div[3]/div/div[3]/div[1]/div/div/div[2]/table/tbody/tr[2]/td[2]/div/div[2]/div[2]")
    __METRO_LEAVE_INPUT = (By.XPATH,"/html/body/div[1]/div[2]/div/div[1]/div[2]/div[2]/div[1]/div[2]/div[1]/input")
    __METRO_ARRIVE_INPUT = (By.XPATH,"/html/body/div[1]/div[2]/div/div[1]/div[2]/div[2]/div[1]/div[2]/div[2]/input")
    __METRO_SUBMIT_BUTTON = (By.XPATH,"/html/body/div[1]/div[2]/div/button")
    __METRO_RESULT_ELE = (By.XPATH,"/html/body/div[1]/div[2]/ul[2]/li/div[1]/div/span[1]")
    __METRO_ENTER = (By.XPATH,"/html/body/div[1]/div[3]/div[3]/div/div[2]/div[2]")
    # 行为
    # 最长的强制等待时间
    timeout = 10

    # 自定义封装查询组件函数，包含指定时间的显示等待
    def find_element(self,driver,by,value):
        try:
            WebDriverWait(driver, self.timeout).until(
                expected_conditions.visibility_of_element_located((by, value))
            )
            return WebDriverWait(driver, self.timeout).until(
                expected_conditions.element_to_be_clickable((by, value))
            )
        except Exception as e:
            print(f"元素定位失败！定位方式：{by}，元素路径：{value}，错误详情：{type(e).__name__}: {str(e)}")
            return None

    # 请在此处插入Selenium+Pytest代码

    @pytest.mark.parametrize(
        "leave_place,arrive_place",
        [
            ["南京大学(鼓楼校区)","新街口商业步行区"],
            ["南京大学(鼓楼校区)","先锋书店(五台山店)"],
            ["东南大学(四牌楼校区)","新街口商业步行区"],
            ["东南大学(四牌楼校区)","先锋书店(五台山店)"]
        ],ids=["BaiDuMap_R001_001","BaiDuMap_R001_002","BaiDuMap_R001_003","BaiDuMap_R001_004"]
    )
    def test_BaiDuMap_R001(self,driver,request,leave_place,arrive_place):
        """

        :param driver: 驱动
        :param request: pytest测试记录
        :param leave_place: 出发地
        :param arrive_place: 目的地
        :return:无
        """
        status = True
        msg = None
        try:
            self.find_element(driver,*self.__WAY).click()
            actions = ActionChains(driver)
            input_ele = self.find_element(driver,*self.__LEAVE_INPUT)
            actions.click(input_ele).send_keys(leave_place).perform()
            arrive_ele = self.find_element(driver,*self.__ARRIVE_INPUT)
            actions.click(arrive_ele).send_keys(arrive_place).perform()
            self.find_element(driver,*self.__QUERY_BUTTON).click()
            # 检测结果是否加载完成
            self.find_element(driver,*self.__MOD[0])
        except Exception as e:
            status = False
            msg = f"{type(e).__name__}: {str(e)}"
        assert status,f"测试异常，原因：{msg}"
        case_id = request.node.callspec.id
        self.take_screenshot(driver,case_id)


    @pytest.mark.parametrize(
        "leave_place,arrive_place,mode",
        [
            ["南京大学(鼓楼校区)","南京大学(仙林校区)",1],
            ["南京大学(鼓楼校区)","南京大学(仙林校区)",2],
            ["南京大学(鼓楼校区)","南京大学(仙林校区)",3],
            ["南京大学(鼓楼校区)","南京大学(仙林校区)",4]
        ],ids=["BaiDuMap_R002_001","BaiDuMap_R002_002","BaiDuMap_R002_003","BaiDuMap_R002_004"]
    )
    def test_BaiDuMap_R002(self,driver,request,leave_place,arrive_place,mode):
        """

        :param driver: 驱动
        :param request: pytest测试记录
        :param leave_place: 出发地
        :param arrive_place: 目的地
        :param mode: 4种给定的路线推荐（1：推荐路线；2.时间短；3.换乘少；4.少步行）
        :return:无
        """
        status = True
        msg = None
        try:
            self.find_element(driver,*self.__WAY).click()
            actions = ActionChains(driver)
            input_ele = self.find_element(driver,*self.__LEAVE_INPUT)
            actions.click(input_ele).send_keys(leave_place).perform()
            arrive_ele = self.find_element(driver,*self.__ARRIVE_INPUT)
            actions.click(arrive_ele).send_keys(arrive_place).perform()
            self.find_element(driver,*self.__QUERY_BUTTON).click()
            # 检测结果是否加载完成
            self.find_element(driver,*self.__MOD[mode-1]).click()
            self.find_element(driver,*self.__MOD[mode-1])
        except Exception as e:
            status = False
            msg = f"{type(e).__name__}: {str(e)}"
        assert status,f"测试异常，原因：{msg}"
        case_id = request.node.callspec.id
        self.take_screenshot(driver,case_id)


    @pytest.mark.parametrize(
        "leave_place,arrive_place",
        [
            ["玄武湖景区","先锋书店（五台山店）"]
        ],ids=["BaiDuMap_R003_001"]
    )
    def test_BaiDuMap_R003(self,driver,request,leave_place,arrive_place):
        """

        :param driver: 驱动
        :param request: pytest测试记录
        :param leave_place: 出发地
        :param arrive_place: 目的地
        :return:无
        """
        status = True
        msg = None
        try:
            self.find_element(driver,*self.__WAY).click()
            actions = ActionChains(driver)
            input_ele = self.find_element(driver,*self.__LEAVE_INPUT)
            actions.click(input_ele).send_keys(leave_place).perform()
            arrive_ele = self.find_element(driver,*self.__ARRIVE_INPUT)
            actions.click(arrive_ele).send_keys(arrive_place).perform()
            self.find_element(driver,*self.__QUERY_BUTTON).click()
            # 点击第一个选为起点
            first_result_ele = self.find_element(driver,By.XPATH, "/html/body/div[1]/div[2]/ul[2]/li/div/div[2]/div[1]/div/div[2]/div/div[1]/table/tbody/tr[1]")
            actions.move_to_element(first_result_ele).perform()
            submit_ele = self.find_element(driver,By.XPATH,"/html/body/div[1]/div[2]/ul[2]/li/div/div[2]/div[1]/div/div[2]/div/div[1]/table/tbody/tr[1]/td[2]/div").click()
            # 检测结果是否加载完成
            self.find_element(driver,*self.__MOD[0])
        except Exception as e:
            status = False
            msg = f"{type(e).__name__}: {str(e)}"
        assert status,f"测试异常，原因：{msg}"
        case_id = request.node.callspec.id
        self.take_screenshot(driver,case_id)


    @pytest.mark.parametrize(
        "city",
        [
            "南京"
        ],ids = ["BaiDuMap_R004_001"]
    )
    def test_BaiDuMap_R004(self,driver,request,city):
        status = True
        msg = None
        try:
            driver.get("https://map.baidu.com/@13225221.26,3748918.53,12z")
            self.find_element(driver,*self.__ROAD_STATUS).click()
            self.find_element(driver,*self.__REFRESH_BUTTON).click()
        except Exception as e:
            status = False
            msg = f"{type(e).__name__}: {str(e)}"
        assert status,f"测试异常：原因:{msg}"
        case_id = request.node.callspec.id
        self.take_screenshot(driver,case_id)


    @pytest.mark.parametrize(
        "city,week_day",
        [
            ["南京",1],
            ["南京",2],
            ["南京",3],
            ["南京",4],
            ["南京",5],
            ["南京",6],
            ["南京",7]
        ],ids = ["BaiDuMap_R005_001","BaiDuMap_R005_002","BaiDuMap_R005_003","BaiDuMap_R005_004","BaiDuMap_R005_005","BaiDuMap_R005_006","BaiDuMap_R005_007"]
    )
    def test_BaiDuMap_R005(self,driver,request,city,week_day):
        status = True
        msg = None
        try:
            driver.get("https://map.baidu.com/@13225221.26,3748918.53,12z")
            self.find_element(driver,*self.__ROAD_STATUS).click()
            self.find_element(driver,*self.__PREDICT_ROAD_STATUS).click()
            week_day_eles = driver.find_elements(*self.__WEEK_DAY)
            week_day_eles[week_day].click()
            time.sleep(15)
        except Exception as e:
            status = False
            msg = f"{type(e).__name__}: {str(e)}"
        assert status,f"测试异常：原因:{msg}"
        case_id = request.node.callspec.id
        self.take_screenshot(driver,case_id)



    @pytest.mark.parametrize(
        "city,target_time",
        [
            ["南京","21:00"]
        ],ids = ["BaiDuMap_R006_001"]
    )
    def test_BaiDuMap_R006(self,driver,request,city,target_time):
        status = True
        msg = None
        try:
            driver.get("https://map.baidu.com/@13225221.26,3748918.53,12z")
            self.find_element(driver,*self.__ROAD_STATUS).click()
            self.find_element(driver,*self.__PREDICT_ROAD_STATUS).click()
            timeline = self.find_element(driver,*self.__TIME_POINT)
            # 目标样式参数
            target_margin_left = "144px"
            # 定位时间轴和目标时间元素
            time_element = driver.find_element(By.XPATH, "/html/body/div[1]/div[3]/div[3]/div/div[3]/div[1]/div/div/div[2]/table/tbody/tr[2]/td[2]/div/div[1]/div")

            step = 5  # 滑动步长
            max_attempts = 50
            attempts = 0

            while attempts < max_attempts:
                # 检查当前时间文本
                current_time = time_element.text.strip()
                print(current_time)
                if current_time == "21:00":
                    break

                # 滑动时间轴（可根据实际方向调整正负）
                ActionChains(driver).click_and_hold(timeline).move_by_offset(step, 0).release().perform()
                attempts += 1
                time.sleep(0.3)  # 等待时间更新
            else:
                print("未找到21:00")
        except Exception as e:
            status = False
            msg = f"{type(e).__name__}: {str(e)}"
        assert status,f"测试异常：原因:{msg}"
        case_id = request.node.callspec.id
        self.take_screenshot(driver,case_id)



    @pytest.mark.parametrize(
        "leave_place,arrive_place",
        [
            ["珠江路","卡子门"],
            ["珠江路","南京站"],
            ["新街口","卡子门"],
            ["大行宫站","马群站"]
        ],ids=["BaiDuMap_R007_001","BaiDuMap_R007_002","BaiDuMap_R007_003","BaiDuMap_R007_004"]
    )
    def test_BaiDuMao_R007(self,driver,request,leave_place,arrive_place):
        status = True
        msg = None
        try:
            driver.get("https://map.baidu.com/@13225221.26,3748918.53,12z")
            self.find_element(driver,*self.__METRO_ENTER).click()
            actions = ActionChains(driver)
            leave_input_ele = self.find_element(driver,*self.__METRO_LEAVE_INPUT)
            actions.click(leave_input_ele).send_keys(leave_place).perform()
            arrive_input_ele = self.find_element(driver,*self.__METRO_ARRIVE_INPUT)
            actions.click(arrive_input_ele).send_keys(arrive_place).perform()
            self.find_element(driver,*self.__METRO_SUBMIT_BUTTON).click()
            # 等待结果渲染
            self.find_element(driver,*self.__METRO_RESULT_ELE)
        except Exception as e:
            status = False
            msg = f"{type(e).__name__}: {str(e)}"
        assert status,f"测试异常：原因:{msg}"
        case_id = request.node.callspec.id
        self.take_screenshot(driver,case_id)

    @pytest.mark.parametrize(
        "leave_place,arrive_place",
        [
            ["大行宫","马群"]
        ],ids=["BaiDuMap_R008_001"]
    )
    def test_BaiDuMao_R008(self,driver,request,leave_place,arrive_place):
        status = True
        msg = None
        try:
            driver.get("https://map.baidu.com/@13225221.26,3748918.53,12z")
            self.find_element(driver,*self.__METRO_ENTER).click()
            leave_place_ele = self.find_element(driver,By.ID,"svgjsImage3984")
            arrive_place_ele = self.find_element(driver,By.ID,"svgjsImage3391")
            actions = ActionChains(driver)
            actions.click(leave_place_ele).click(arrive_place_ele).perform()
            # 等待结果渲染
            self.find_element(driver,*self.__METRO_RESULT_ELE)
        except Exception as e:
            status = False
            msg = f"{type(e).__name__}: {str(e)}"
        assert status,f"测试异常：原因:{msg}"
        case_id = request.node.callspec.id
        self.take_screenshot(driver,case_id)



    # test-code-start

    @staticmethod
    def take_screenshot(driver, file_name):
        timestamp = datetime.now().strftime( "%H%M%S%d%f" )[:-3]
        timestamped_file_name = f"{timestamp}_{file_name}.png"
        screenshots_dir = "screenshots"
        if not os.path.exists( screenshots_dir ):
            os.makedirs( screenshots_dir )
        screenshot_file_path = os.path.join( screenshots_dir, timestamped_file_name )
        driver.save_screenshot( screenshot_file_path )
